Skip to content

fix: fetch cumulative update pages with native fetch to avoid 403s#258

Merged
dhensby merged 1 commit into
masterfrom
fix/cu-download-403
Jul 19, 2026
Merged

fix: fetch cumulative update pages with native fetch to avoid 403s#258
dhensby merged 1 commit into
masterfrom
fix/cu-download-403

Conversation

@arthurschreiber

@arthurschreiber arthurschreiber commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Since v3.1.0 (which pulled in @actions/http-client >= 3.0.1), cumulative update installation has been silently broken: the Microsoft download pages scraped by downloadUpdateInstaller respond with an instant 403 and SQL Server gets installed as plain RTM, with only a warning in the logs.

The trigger is the request shape of newer @actions/http-client versions, which Microsoft's CDN edge rejects from runner IPs. Notably it is not simply the user agent string: a probe from real windows-2022/windows-2025 runners showed that native fetch requests succeed with any user agent — including actions/http-client actions_orchestration_id/... — while an unmodified v4 install job running minutes later still got a 403 from its http-client request. The old http-client 2.2.x request (which sent no user-agent header at all) also passed.

Evidence from tediousjs/tedious CI on 2026-07-19 (same runner pool, same day):

  • setup-sqlserver@v4: 403 on the 2022 CU page in 6 consecutive run attempts between 11:26 and 15:41 UTC (run) → SQL Server 2022 RTM (16.0.1000) → tedious' TDS 8.0 strict-encryption integration test fails against an RTM server bug.
  • setup-sqlserver@v2: successful scrape at 15:09 UTC (run) → CU26 (16.0.4265.3) installed, tests green.
  • UA probe via native fetch at ~15:45 UTC: HTTP 200 with the download link found for all 8 user-agent variants tested, on both Windows runner images.

Changes

  • downloadUpdateInstaller scrapes the update page with native fetch, sending a transparent tediousjs/setup-sqlserver user agent and accept: text/html header.
  • The actual .exe downloads are unaffected — they keep using @actions/tool-cache against download.microsoft.com, which does not reject these requests.
  • Dropped the now-unused direct @actions/http-client dependency and rebuilt lib/.
  • Tests mock global fetch instead of the http-client module; added a test for the non-2xx warning path.

Verification

A failed CU download only warns, so a green runaction job is not sufficient — check the sql-2022 job log for Downloading cumulative update from https://download.microsoft.com/... and (RTM-CU26) in the installed version output. An earlier revision of this PR (browser-like user agent) already passed this check; the current revision only changes the user-agent string, which the probe showed is not load-bearing.

🤖 Generated with Claude Code

Since @actions/http-client 3.0.1, requests carry a default user agent of
`actions/http-client actions_orchestration_id/<id>` (previously no
user-agent header was sent at all). The Microsoft download pages scraped
by downloadUpdateInstaller reject requests with that user agent with an
instant 403, so cumulative updates were silently skipped and SQL Server
was installed as plain RTM.

Switch the page scrape to the native fetch API with a browser-like user
agent. The actual .exe downloads from download.microsoft.com are
unaffected and keep using @actions/tool-cache.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes cumulative update (CU) page scraping by switching downloadUpdateInstaller from @actions/http-client to native fetch, avoiding Microsoft download page 403 responses that have prevented CU installation since newer @actions/http-client versions were introduced.

Changes:

  • Replaced CU update-page HTTP retrieval with native fetch (custom UA + HTML accept header) while keeping the actual .exe download path unchanged.
  • Updated tests to mock globalThis.fetch and added coverage for the non-2xx warning/return-empty path.
  • Removed the now-unused direct @actions/http-client dependency from the package manifests.

Reviewed changes

Copilot reviewed 3 out of 6 changed files in this pull request and generated no comments.

File Description
src/utils.ts Uses native fetch to scrape CU download pages and logs status via Response.status.
test/utils.ts Switches mocks from HttpClient to globalThis.fetch and adds a rejected-request test.
package.json Removes direct dependency on @actions/http-client.
package-lock.json Updates lockfile to reflect dependency removal.

@dhensby
dhensby merged commit 7edd3a4 into master Jul 19, 2026
33 checks passed
@dhensby
dhensby deleted the fix/cu-download-403 branch July 19, 2026 20:39
@arthurschreiber

Copy link
Copy Markdown
Contributor Author

@dhensby You were a bit too quick to merge this 😬 I was about to push some additional changes / cleanup. Let me open a new PR for that.

@dhensby

dhensby commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Sorry! thanks

@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 4.0.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants